import edu.mit.csail.sdg.alloy4compiler.translator.A4Solution; 

import javax.print.Doc;
import javax.xml.parsers.*; 
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.*; 
import org.xml.sax.*; 
import java.io.*; 
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

//Cette classe manipule les solutions et rempli un fichier html
public class Afficheur {
	
	//Modifie le code html de la page priorite avec le DOM 
	public static String afficheRDV(A4Solution ans) {

		String priorites = "";
		Node field = ExempleDOM.getPartieFix(PlanbycoServer.ALLOYRESULTAT, "field", 0); 
		System.out.println(field.getNodeName());
		NodeList tuples = ((Element) field).getElementsByTagName("tuple");
		for (int i=0;i<tuples.getLength();i++){
			Element unTuple = (Element) tuples.item(i);
			NodeList atomes = unTuple.getElementsByTagName("atom");
			priorites += "<p>plage : ";
			priorites += ((Element) atomes.item(0)).getAttribute("label");
			priorites += " --> ";
			priorites += ((Element) atomes.item(1)).getAttribute("label");
			priorites += " </p> ";
		}

		priorites += "</br>";

		field = ExempleDOM.getPartieFix(PlanbycoServer.ALLOYRESULTAT, "field", 1); 
		System.out.println(field.getNodeName());
		tuples = ((Element) field).getElementsByTagName("tuple");

		TreeMap<String, Integer> treeMap = new TreeMap<String, Integer>();
		
		for (int i=0;i<tuples.getLength();i++){
			Element unTuple = (Element) tuples.item(i);
			NodeList atomes = unTuple.getElementsByTagName("atom");
			String key = ((Element) atomes.item(1)).getAttribute("label");
			if (treeMap.get(key)==null){
				int value=1;
				treeMap.put(key, value);
			}else {
				treeMap.put(key, treeMap.get(key)+1);
			}
			
		}
		for (int i = 0;i<tuples.getLength();i++){
			Element unTuple = (Element) tuples.item(i);
			NodeList atomes = unTuple.getElementsByTagName("atom");
			if (!treeMap.containsKey(((Element) atomes.item(0)).getAttribute("label"))){
				treeMap.put(((Element) atomes.item(0)).getAttribute("label"), 0);
			}
		}
		//treeMap.values();
		treeMap = doSort(treeMap);
		
		Set<String> plages = treeMap.keySet();
		for (String s : plages){
			priorites += " <p> ";
			priorites += s;
			priorites += " </p> ";
		}
		
		priorites += "<input type=\"button\" value=\"Next\" onclick=\"self.location.href='http://localhost:8080/prioritaire.html?next'\"";

		return priorites;
	}
	

	public static String afficheEmploiDuTemps(A4Solution ans) {
		
		
		//------On construit une liste de "Jours" (un Jour contient des "Cases"), ensuite on l'affichera dans l'ordre grace au DOM------//
		ArrayList<Jour> semaine = new ArrayList<Jour>(); 
		for (Jour j: semaine)
			j=null;
		
		//------on rempli la semaine de jours------//
		Node jourParent = ExempleDOM.recherche(PlanbycoServer.CHEMINALS+PlanbycoServer.ALLOYRESULTAT, "sig", "this/Jour");
		String idJourParent = ((Element) jourParent).getAttribute("ID");
		
		for (Node jour : ExempleDOM.listeNode(PlanbycoServer.CHEMINALS+PlanbycoServer.ALLOYRESULTAT, "sig", idJourParent)){
			semaine.add(new Jour(((Element) jour.getChildNodes().item(1)).getAttribute("label")));
		}
		
		//------on rempli chaque jours avec les plages associes (dans l'ordre de priorite (precedeP))------//
		Node fieldAppartient = ExempleDOM.getPartieFix(PlanbycoServer.CHEMINALS+PlanbycoServer.ALLOYRESULTAT, "field", 4);
		NodeList tuplesAppartient = fieldAppartient.getChildNodes();
		
		//Pour chaque plage(tuples) dans precedeP
		Node fieldPrecedeP = ExempleDOM.getPartieFix(PlanbycoServer.CHEMINALS+PlanbycoServer.ALLOYRESULTAT, "field", 5);
		NodeList tuplesPrecedeP = fieldPrecedeP.getChildNodes();
		
		for (int i=0;i<tuplesPrecedeP.getLength();i++){
			int j=0;
			if (tuplesPrecedeP.item(i).getNodeType()!=3){
				boolean trouve=false;
				while (j<tuplesAppartient.getLength() && trouve!=true){
					if (tuplesAppartient.item(j).getNodeType()!=3 && (((Element) tuplesPrecedeP.item(i).getChildNodes().item(1)).getAttribute("label").equals(((Element) tuplesAppartient.item(j).getChildNodes().item(1)).getAttribute("label")))==true){
						trouve=true;
					}else {
						j++;
					}
				}
				if (j==tuplesAppartient.getLength()){
					System.out.print("Probleme");
				}else {
					int k=0;
					boolean trouve2=false;
					while (k<semaine.size() && trouve2!=true){
						if (tuplesAppartient.item(j).getNodeType()!=3 && semaine.get(k).getNom().equals(((Element) tuplesAppartient.item(j).getChildNodes().item(3)).getAttribute("label"))==true){
							trouve2=true;
						}else {
							k++;
						}
					}
					if (trouve2==true){
						semaine.get(k).ajouterPlage(new PlageHoraire(((Element) tuplesPrecedeP.item(i).getChildNodes().item(1)).getAttribute("label")));
					}
				}
			}
		}
		
		
		//Le/Les groupe
		Node fieldOccupee = ExempleDOM.getPartieFix(PlanbycoServer.CHEMINALS+PlanbycoServer.ALLOYRESULTAT, "field", 0);
		NodeList tuplesOccupee = fieldOccupee.getChildNodes();
		
		for (int i=0;i<tuplesOccupee.getLength();i++){
			if (tuplesOccupee.item(i).getNodeType()!=3){
				Node tuple = tuplesOccupee.item(i);
				Node atome1 = tuple.getChildNodes().item(1);
				Node atome2 = tuple.getChildNodes().item(3);
				int j = 0;
				while (j<semaine.size() && semaine.get(j).recherchePlage(((Element) atome1).getAttribute("label"))==null){
					j++;
				}
				if (j!=semaine.size()){
					semaine.get(j).recherchePlage(((Element) atome1).getAttribute("label")).setGroupePlageHoraire(((Element) atome2).getAttribute("label"));
				}
			}
		}
		

		//Le/les type de plage		
		Node fieldType = ExempleDOM.getPartieFix(PlanbycoServer.CHEMINALS+PlanbycoServer.ALLOYRESULTAT, "field", 1);
		NodeList tuplesType = fieldType.getChildNodes();
		
		for (int i=0;i<tuplesType.getLength();i++){
			if (tuplesType.item(i).getNodeType()!=3){
				Node tuple = tuplesType.item(i);
				Node atome1 = tuple.getChildNodes().item(1);
				Node atome2 = tuple.getChildNodes().item(3);
				int j = 0;
				while (j<semaine.size() && semaine.get(j).recherchePlage(((Element) atome1).getAttribute("label"))==null){
					j++;
				}
				if (j!=semaine.size()){
					semaine.get(j).recherchePlage(((Element) atome1).getAttribute("label")).setTypePlageHoraire(((Element) atome2).getAttribute("label"));
				}
			}
		}
		

		//Le/les enseignants
		Node fieldPrend = ExempleDOM.getPartieFix(PlanbycoServer.CHEMINALS+PlanbycoServer.ALLOYRESULTAT, "field", 3);
		NodeList tuplesPrend = fieldPrend.getChildNodes();
		
		for (int i=0;i<tuplesPrend.getLength();i++){
			if (tuplesPrend.item(i).getNodeType()!=3){
				Node tuple = tuplesPrend.item(i);
				Node atome1 = tuple.getChildNodes().item(1);
				Node atome2 = tuple.getChildNodes().item(3);
				int j = 0;
				while (j<semaine.size() && semaine.get(j).recherchePlage(((Element) atome1).getAttribute("label"))==null){
					j++;
				}
				if (j!=semaine.size()){
					semaine.get(j).recherchePlage(((Element) atome1).getAttribute("label")).setEnseignantPlageHoraire(((Element) atome2).getAttribute("label"));
				}
			}
		}
		
		
		
		//------ecrit la semaine dans le fichier html------//
		Document document = ExempleDOM.parser(PlanbycoServer.CHEMINALS+PlanbycoServer.CHEMINHTML +PlanbycoServer.EDTHTML);
		Node body = document.getElementsByTagName("div").item(0);
		Element table = document.createElement("table");
		table.setAttribute("summary", "");
		table.setAttribute("border", "1");
		table.setAttribute("width", "80%");
		table.setAttribute("align", "center");
		while (body.hasChildNodes())
			body.removeChild(body.getFirstChild());
		body.appendChild(table);
		
		int nbPlageMax = 0;
		for (Jour j : semaine)
			nbPlageMax=(j.getNbPlages()>nbPlageMax)?j.getNbPlages():nbPlageMax;
		for (int i=0; i<nbPlageMax;i++){
			Node ligne = document.createElement("tr");
			((Node) table).appendChild(ligne);
			
			for (int j=0;j<semaine.size();j++){
				if (semaine.get(j).getPlagesHoraires().size()>i){
					ligne.appendChild(semaine.get(j).getPlagesHoraires().get(i).creeElementCorrespondant(document));
				}
			}
		}
		TransformerFactory transformerFactory = TransformerFactory.newInstance();
		try {
			Transformer transformer = transformerFactory.newTransformer();
			DOMSource source = new DOMSource(document);
			StreamResult result = new StreamResult(new File(PlanbycoServer.CHEMINALS+PlanbycoServer.CHEMINHTML +PlanbycoServer.EDTHTML));
			transformer.transform(source, result);
		} catch (TransformerConfigurationException e) {
			e.printStackTrace();
		} catch (TransformerException tfe) {
			tfe.printStackTrace();
		}
		
		return "";
	}
	
	public static TreeMap<String, Integer> doSort(Map<String, Integer>  map) {
		 Comparator<String> comparator = new ValueComparator(map);
		 TreeMap<String, Integer> sortedMap = new TreeMap<String, Integer>(comparator);
		 sortedMap.putAll(map);
		 return sortedMap;
	}
}

class ValueComparator implements Comparator<String> {

    Map<String, Integer> base;
    public ValueComparator(Map<String, Integer> base) {
        this.base = base;
    }

    public int compare(String a, String b) {
        if (base.get(a) >= base.get(b)) {
            return 1;
        } else {
            return -1;
        } // returning 0 would merge keys
    }
}
